﻿////////////////////////////////////////////////////////////////////////////
//                                                                        //
//                       Copyright (c) 2000-2023                          //
//                              Wang Hua                                  //
//                                                                        //
////////////////////////////////////////////////////////////////////////////

// AsNLEquation.cpp
//
//////////////////////////////////////////////////////////////////////


#include "AsNLEquation.h"
#include <iostream>


using namespace std;



//***************************************************************************
/// 非线性方程求解的二分法
/// Using bisection, find the root of a function func known to lie between x1 and 
///   x2. The root will be refined until its accuracy is +-xacc.
/// @Author	Wang Hua
/// @Date	2006.2.14 
/// @Input
/// @Param	func
/// @Param	x1		包含根的区间的一个端点
/// @Param	x2		包含根的区间的另一个端点
/// @Param	xacc	精度，区间小于+-acc时返回
/// @Output
/// @Param	root	返回计算得到的根
/// @Return	是否计算成功
//***************************************************************************
bool AsNLEBisection(const CFunc11& func, double x1, double x2, 
				double xacc, double& root)
{
	//<<Numerical Recipes in C++>> p358 rtbis

	double dx,f,fmid,xmid,rtb;

	if ( !func(x1, f) )
		return false;
	if ( !func(x2, fmid) )
		return false;

	//assert ( (f>=0.0 && fmid<=0.0) || (f<=0.0 && fmid>=0.0) );
    if (f*fmid>0.0)
    {
        root = 0;
		return false;
    }

	rtb = f<0.0 ? (dx=x2-x1,x1) : (dx=x1-x2,x2);
	do {
		if ( !func(xmid = rtb+(dx*=0.5), fmid) )
			return false;
		if (fmid<=0.0)
			rtb=xmid;
	} while( fabs(dx)>xacc && fmid!=0 );
	root = xmid;
	return true;
}

